/****************************************************************************

 control-box.hpp - Container for control widgets

Copyright (C) Michael R Fisher <mfisher31@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA

****************************************************************************/

#ifndef CONTROLBOX_HPP_
#define CONTROLBOX_HPP_

#include <gtkmm.h>
#include "plugin.hpp"

using namespace Gtk;
using namespace sigc;
using namespace std;



class ControlBox : public Gtk::VBox
{
protected:
  Gtk::Table m_table;
  Gtk::Frame m_frame;
  uint32_t ncontrols;

public:
  ControlBox() : ncontrols(0), m_table(3,3)
  {
    m_frame.add(m_table);
    m_frame.set_shadow_type(Gtk::SHADOW_IN);
    m_frame.set_border_width(3);
    m_table.set_border_width(6);
    pack_start(m_frame);
  }

  ~ControlBox()
  {

  }

  // This is a template function so that different kinds of widgets can
  // easilly be made into controls.  All the widget has to do is
  // inherit Gtk::Scale and this should work just fine.  See control-widget.hpp

  template<class W>
  Adjustment* add(Port& port)

  {
    W* widget = new W();
    Gtk::Scale* ctl = static_cast<Gtk::Scale*>(widget);

    Adjustment *adj;
    Label *lbl = manage( new Label(port.name));
    SpinButton *spin = manage( new  SpinButton());

    // TODO: set adj increment values based on the range of the
    // control port.

    adj = new Adjustment (port.default_value,
                          port.minimum_value, // double lower,
                          port.maximum_value, //double upper,
                          0.0001, //double step_increment=1,
                          0.1,       //double page_increment=10,
                          0);       //double page_size=0)

    ctl->set_draw_value(false);
    ctl->set_size_request(175,-1);

    lbl->set_alignment(0,0.5);

    spin->set_digits(2);

    m_table.attach(*lbl,0,1,ncontrols,ncontrols+1);
    m_table.attach(*ctl,1,2,ncontrols,ncontrols+1);
    m_table.attach(*spin,2,3,ncontrols,ncontrols+1);

    ++ncontrols;

    slot<float> get_value = mem_fun(*adj, &Adjustment::get_value);
    slot<void, float> control_changed = bind<0>(signal_control_changed, port.symbol);
    slot<void> function = compose(control_changed, get_value);
    adj->signal_value_changed().connect(function);

    ctl->set_adjustment(*adj);
    spin->set_adjustment(*adj);

    return adj;
  }

  sigc::signal<void,std::string&,float> signal_control_changed;

};

#endif /* CONTROLBOX_HPP_ */
